<template>
    <div class="app-container">
        <!-- 搜索栏 -->
        <el-form :model="queryParams" :inline="true" v-show="showSearch">
            <el-form-item label="主题">
                <el-input @keyup.enter="handleQuery" v-model="queryParams.keyword" style="width: 150px"
                          placeholder="请输入题目主题" clearable/>
            </el-form-item>
            <el-form-item label="标签">
                <el-select v-model="queryParams.tagId" placeholder="请选择标签" clearable filterable
                           @visible-change="getTag"
                           style="width: 130px">
                    <el-option v-for="item in tagList" :key="item.id" :label="item.tagName" :value="item.id">
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
            </el-form-item>
        </el-form>
        <!-- 头部操作按钮 -->
        <el-row :gutter="10" class="mb15">
            <el-col :span="1.5">
                <el-button type="primary" plain icon="Position" @click="handleOpen()">发出题目</el-button>
                <el-button type="danger" plain icon="Delete" :disabled="quizIdList.length === 0"
                           @click="handleDelete(undefined)">批量删除
                </el-button>
            </el-col>
            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
        <!-- 表格展示 -->
        <el-table :data="quizList" @selection-change="handleSelectionChange" v-loading="loading"
                  border height="500" :default-sort="{ prop: 'createTime', order: 'descending' }">
            <!-- 表格列 -->
            <el-table-column type="selection" width="55" align="center"></el-table-column>
            <!-- 题目标题 -->
            <el-table-column prop="title" label="主题" align="center"></el-table-column>
            <!-- 发表人 -->
            <el-table-column prop="userId" label="用户ID" align="center" width="70"></el-table-column>
            <!-- 题目标签 -->
            <el-table-column prop="tagVOList" label="标签" width="160" align="center" resizable>
                <template #default="scope">
                    <el-tag v-for="item of scope.row.tagVOList" :key="item.tagId"
                            style="margin-right: 0.2rem; margin-top: 0.2rem">
                        {{ item.tagName }}
                    </el-tag>
                </template>
            </el-table-column>
            <!-- 题目浏览量 -->
            <el-table-column prop="viewCount" label="浏览量" width="80" align="center" sortable>
            </el-table-column>
            <!-- 题目点赞量 -->
            <el-table-column prop="likeNumber" label="点赞数" width="80" align="center" sortable>
            </el-table-column>
            <!-- 题目收藏量 -->
            <el-table-column prop="collectNumber" label="收藏数" width="80" align="center" sortable>
            </el-table-column>
            <!-- 创建时间 -->
            <el-table-column prop="createTime" width="130" label="创建时间" align="center" sortable>
                <template #default="scope">
                    <div class="create-time">
                        <el-icon>
                            <clock/>
                        </el-icon>
                        <span style="margin-left: 10px">{{ formatDate(scope.row.createTime) }}</span>
                    </div>
                </template>
            </el-table-column>
            <!-- 操作 -->
            <el-table-column width="150" label="操作" align="center" fixed="right">
                <template #default="scope">
                    <el-button type="primary" icon="Edit" link @click="handleEdit(scope.row.id)">
                        编辑
                    </el-button>
                    <el-button type="danger" icon="Delete" link @click="handleDelete(scope.row.id)">
                        删除
                    </el-button>
                </template>
            </el-table-column>
        </el-table>
        <!-- 分页 -->
        <pagination v-if="count > 0" :total="count" v-model:page="queryParams.pageNum"
                    v-model:limit="queryParams.pageSize" @pagination="getList"/>
        <!-- 发出或修改对话框 -->
        <el-dialog title="发出题目" v-model="addOrUpdate" width="600px" top="0.5vh" @close="cancel"
                   append-to-body center draggable>
            <el-form ref="quizFormRef" label-width="80px" :model="quizForm" :rules="rules">
                <!-- 题目主题 -->
                <el-form-item label="题目主题" prop="type">
                    <el-input placeholder="请输入主题" v-model="quizForm.title" style="width: 350px;"/>
                </el-form-item>
                <!-- 题目内容 -->
                <el-form-item label="题目内容" prop="content">
                    <el-input v-model="quizForm.content" :rows="2" type="textarea" placeholder="请输入题目内容"/>
                </el-form-item>
                <!-- 题目标签 -->
                <el-form-item label="题目标签" prop="tagNameList">
                    <el-tag v-for="(item, index) of quizForm.tagNameList" :key="index" :disable-transitions="true"
                            :closable="true" @close="removeTag(item)" style="margin-right: 1rem;">
                        {{ item }}
                    </el-tag>
                    <!-- 标签选项 -->
                    <el-popover placement="bottom-start" :offset="20" width="420" trigger="click"
                                v-if="quizForm.tagNameList.length < 3"
                                :popper-style="popoverStyle">
                        <template #reference>
                            <el-button type="success" plain icon="Plus">添加</el-button>
                        </template>
                        <div class="popover-title">标签</div>
                        <!-- 搜索框 -->
                        <el-autocomplete style="width: 100%" v-model="tagName" :fetch-suggestions="searchTag"
                                         placeholder="请输入标签名搜索,enter可添加自定义标签" :trigger-on-focus="false"
                                         @keyup.enter="saveTag"
                                         @select="handleSelectTag">
                            <template #default="{ item }">
                                <div>{{ item.tagName }}</div>
                            </template>
                        </el-autocomplete>
                        <!-- 标签 -->
                        <div class="popover-container">
                            <div style="margin-bottom: 1rem">点击标签进行添加</div>
                            <el-tag v-for="(item, index) of tagList" :key="index" :class="tagClass(item.tagName)"
                                    @click="addTag(item.tagName)" style="margin-right: 1rem;">
                                {{ item.tagName }}
                            </el-tag>
                        </div>
                    </el-popover>
                </el-form-item>
            </el-form>
            <el-row :gutter="10" align="middle" style="margin-top: 10px;">
                <el-col :span="1.5">
                    <!-- 图片上传 -->
                    <el-upload accept="image/*" multiple action="/api/admin/quizImage/upload"
                               :show-file-list="false" :headers="authorization"
                               :before-upload="beforeUpload" :on-success="handleSuccess">
                        点击进行图片上传
                        <svg-icon icon-class="album" size="1.5rem" color="#838383"
                                  style="padding-top:0.1rem;"></svg-icon>
                    </el-upload>
                </el-col>
            </el-row>
            <!-- 图片上传 -->
            <el-upload accept="image/*" v-show="uploadList.length > 0" action="/api/admin/quizImage/upload"
                       :headers="authorization" list-type="picture-card" :file-list="uploadList" multiple
                       :before-upload="beforeUpload" :on-success="handleSuccess" :on-remove="handleRemove"
                       :on-preview="handlePictureCardPreview" style="margin-top:1rem;">
                <el-icon>
                    <Plus/>
                </el-icon>
            </el-upload>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="success" @click="submitForm">保存题目</el-button>
                    <el-button @click="cancel">取 消</el-button>
                </div>
            </template>
        </el-dialog>
        <!-- 图片预览 -->
        <el-dialog v-model="dialogVisible" append-to-body>
            <img :src="dialogImageUrl" style="max-width:100%" alt="图片"/>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import {
    addQuiz,
    deleteQuiz,
    editQuiz,
    getQTagOption,
    getQuizList,
    getTagOption,
    updateQuiz,
} from '@/api/quiz';
import {Quiz, QuizForm, QuizQuery, TagVO} from '@/api/quiz/types';
import {formatDate} from "@/utils/date";
import {messageConfirm, notifySuccess} from '@/utils/modal';
import {computed, onMounted, reactive, ref, toRefs} from 'vue';
import {AxiosResponse} from "axios";
import {FormInstance, FormRules, UploadFile, UploadRawFile} from "element-plus";
import * as imageConversion from "image-conversion";
import {getToken, token_prefix} from "@/utils/token";
import {Picture} from "@/model";

const quizFormRef = ref<FormInstance>();
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const rules = reactive<FormRules>({
    tagNameList: [{required: true, message: "记录标签不能为空", trigger: "blur"}],
});
const authorization = computed(() => {
    return {
        Authorization: token_prefix + getToken(),
    }
});
const tagClass = computed(() => {
    return function (item: string) {
        const index = quizForm.value.tagNameList.indexOf(item);
        return index !== -1 ? "tag-item-select" : "tag-item";
    };
});
const data = reactive({
    addOrUpdate: false,
    count: 0,
    showSearch: true,
    loading: false,
    title: "",
    queryParams: {
        pageNum: 1,
        pageSize: 10,
    } as QuizQuery,
    tagList: [] as TagVO[],
    quizIdList: [] as number[],
    quizList: [] as Quiz[],
    quizForm: {
        id: undefined,
        userId: 1,
        title: "",
        content: "",
        tagNameList: [],
        images: undefined
    } as QuizForm,
    tagName: "",
    uploadList: [] as Picture[],
    popoverStyle: {
        backgroundColor: '#e8eaf1',
        color: '#333',
        boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)'
    }
});
const {
    addOrUpdate, count, showSearch, loading, title,
    queryParams, tagList, quizIdList, quizList,
    quizForm, tagName, uploadList, popoverStyle
} = toRefs(data);
const handleSelectionChange = (selection: Quiz[]) => {
    quizIdList.value = selection.map((item) => item.id);
};
const handleOpen = () => {
    title.value = "发出题目";
    addOrUpdate.value = true;
    getTagOption().then(({data}) => {
        tagList.value = data.data;
    });
}
const handleEdit = (quizId: number) => {
    editQuiz(quizId).then(({data}) => {
        if (data.flag) {
            quizForm.value = data.data;
            if (data.data.imgList) {
                data.data.imgList.forEach((item) => {
                    uploadList.value.push({url: item});
                });
            }
            title.value = "修改题目";
            addOrUpdate.value = true;
        }
    })
    getTagOption().then(({data}) => {
        tagList.value = data.data;
    });
};
const handleDelete = (id?: number) => {
    let ids: number[] = [];
    if (id == undefined) {
        ids = quizIdList.value;
    } else {
        ids = [id];
    }
    messageConfirm("确认删除已选中的数据项?").then(() => {
        deleteQuiz(ids).then(({data}) => {
            if (data.flag) {
                notifySuccess(data.msg);
                getList();
            }
        });
    }).catch(() => {
    });
};
// 操作标签 start
const getTag = (val: boolean) => {
    if (val) {
        getQTagOption().then(({data}) => {
            tagList.value = data.data;
        });
    }
};
const removeTag = (item: string) => {
    const index = quizForm.value.tagNameList.indexOf(item);
    quizForm.value.tagNameList.splice(index, 1);
};
const handleSelectTag = (item: TagVO) => {
    addTag(item.tagName);
};
const saveTag = () => {
    if (tagName.value.trim() != "") {
        addTag(tagName.value);
        tagName.value = "";
    }
};
const addTag = (item: string) => {
    if (quizForm.value.tagNameList.indexOf(item) == -1) {
        quizForm.value.tagNameList.push(item);
    }
};
const searchTag = (keyword: string, cb: (arg: TagVO[]) => void) => {
    const results = keyword
        ? tagList.value.filter(createTagFilter(keyword))
        : tagList.value
    cb(results);
};
const createTagFilter = (queryString: string) => {
    return (restaurant: TagVO) => {
        return (
            restaurant.tagName.indexOf(queryString) !== -1
        )
    }
};
// 操作标签 end
// 取消
const cancel = () => {
    addOrUpdate.value = false;
    quizFormRef.value?.clearValidate();
    reset();
};
// 重置表单
const reset = () => {
    quizForm.value = {
        id: undefined,
        userId: 1,
        title: "",
        content: "",
        tagNameList: [],
        images: undefined
    };
    uploadList.value = [];
};
const beforeUpload = (rawFile: UploadRawFile) => {
    return new Promise(resolve => {
        if (rawFile.size / 1024 < 200) {
            resolve(rawFile);
        }
        // 压缩到200KB,这里的200就是要压缩的大小,可自定义
        imageConversion
            .compressAccurately(rawFile, 200)
            .then(res => {
                resolve(res);
            });
    });
};
const handleSuccess = (response: AxiosResponse) => {
    uploadList.value.push({url: response.data});
};
const handleRemove = (file: UploadFile) => {
    uploadList.value.forEach((item, index) => {
        if (item.url == file.url) {
            uploadList.value.splice(index, 1);
        }
    });
};
const handlePictureCardPreview = (file: UploadFile) => {
    dialogImageUrl.value = file.url!;
    dialogVisible.value = true;
};
const submitForm = () => {
    quizFormRef.value?.validate((valid) => {
        if (valid) {
            // 转换图片
            if (uploadList.value.length > 0) {
                let imgList: string[] = [];
                uploadList.value.forEach((item) => {
                    imgList.push(item.url);
                });
                quizForm.value.images = JSON.stringify(imgList);
            } else {
                quizForm.value.images = "";
            }
            if (quizForm.value.id !== undefined) {
                updateQuiz(quizForm.value).then(({data}) => {
                    if (data.flag) {
                        uploadList.value = [];
                        notifySuccess(data.msg);
                        getList();
                    }
                    cancel();
                });
            } else {
                addQuiz(quizForm.value).then(({data}) => {
                    if (data.flag) {
                        notifySuccess(data.msg);
                        getList();
                    }
                    cancel();
                });
            }
        }
    })
};
const getList = () => {
    loading.value = true;
    getQuizList(queryParams.value).then(({data}) => {
        quizList.value = data.rows;
        count.value = data.total;
        loading.value = false;
    })
};
const handleQuery = () => {
    queryParams.value.pageNum = 1;
    getList();
};
onMounted(() => {
    getList();
});
</script>

<style scoped>
.popover-container {
    margin-top: 1rem;
    height: 260px;
    overflow-y: auto;
}

.tag-item {
    margin-right: 1rem;
    margin-bottom: 1rem;
    cursor: pointer;
}

.tag-item-select {
    margin-right: 1rem;
    margin-bottom: 1rem;
    cursor: not-allowed;
    color: #ccccd8 !important;
}
</style>